package com.sali.commons.aop.log;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sali.commons.annotation.ApiLog;
import com.sali.utils.threadlocal.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Pointcut("@annotation(com.sali.commons.annotation.ApiLog)")
    public void cut(){}


    @Around("cut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        ApiLog methodAnnotation = method.getAnnotation(ApiLog.class);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Object[] args = joinPoint.getArgs();
        Object arg = args==null || args.length==0? null: args[0];
        String argStr;
        try {
            argStr = JSON.toJSONString(arg, SerializerFeature.WriteMapNullValue);
        } catch (Exception e) {
            argStr = null;
        }
        log.info("========================= start =========================");

        log.info("操作人是 ：{}", UserThreadLocal.get());
        log.info("请求业务 ：{}", methodAnnotation.value());
        log.info("请求路径 ：{}", request.getRequestURL().toString());
        log.info("请求方法 ：{}", request.getMethod());
        log.info("class类 ：{}#{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        log.info("请求地址 ：{}", request.getRemoteAddr());
        log.info("请求参数 ：{}", argStr);

        // 计时
        long start = System.currentTimeMillis();
        // 执行方法，连接点
        Object result = joinPoint.proceed();
        // 查看耗时
        log.info("请求出参 ：{}", result);
        log.info("请求耗时 ：{} ms", System.currentTimeMillis()-start);
		log.info("========================== end ==========================" + System.lineSeparator());
        return result;
    }
}
